#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
市场特征缓存机制使用示例

这个脚本展示了如何在实际项目中使用市场特征缓存机制，
包括首次运行、缓存复用、增量更新等场景。
"""

import pandas as pd
import time
from datetime import datetime
from func import (
    add_market_features, 
    get_cache_info,
    clear_market_features_cache
)

def demonstrate_cache_usage():
    """演示缓存机制的实际使用"""
    print("=" * 80)
    print("🎯 市场特征缓存机制使用示例")
    print("=" * 80)
    
    # 模拟真实的基金数据
    print("\n📋 创建模拟基金数据...")
    
    # 创建一个月的数据
    dates = pd.date_range('2024-06-01', '2024-06-30', freq='D')
    fund_codes = ['000001', '000086', '000192', '000385', '000478']
    
    data_rows = []
    for date in dates:
        for fund_code in fund_codes:
            # 模拟申购赎回数据
            apply_amt = abs(hash(f"{fund_code}_{date}_apply") % 50000) + 10000
            redeem_amt = abs(hash(f"{fund_code}_{date}_redeem") % 30000) + 5000
            
            # 模拟UV数据
            uv1 = abs(hash(f"{fund_code}_{date}_uv1") % 2000) + 500
            uv2 = abs(hash(f"{fund_code}_{date}_uv2") % 1500) + 300
            uv3 = abs(hash(f"{fund_code}_{date}_uv3") % 1000) + 200
            
            data_rows.append({
                'fund_code': fund_code,
                'transaction_date': date,
                'apply_amt': apply_amt,
                'redeem_amt': redeem_amt,
                'uv_key_page_1': uv1,
                'uv_key_page_2': uv2,
                'uv_key_page_3': uv3
            })
    
    df = pd.DataFrame(data_rows)
    print(f"📊 生成数据: {df.shape[0]} 行，{len(fund_codes)} 个基金，{len(dates)} 天")
    print(f"📅 日期范围: {df['transaction_date'].min().strftime('%Y-%m-%d')} 到 {df['transaction_date'].max().strftime('%Y-%m-%d')}")
    
    cache_path = "demo_market_cache.pkl"
    
    # 场景1：首次运行（创建缓存）
    print("\n" + "="*60)
    print("🚀 场景1：首次运行（创建缓存）")
    print("="*60)
    
    # 清理可能存在的旧缓存
    clear_market_features_cache(cache_path)
    
    print("🔄 开始首次特征工程...")
    start_time = time.time()
    df_with_features = add_market_features(df.copy(), cache_path=cache_path)
    first_run_time = time.time() - start_time
    
    print(f"⏱️ 首次运行耗时: {first_run_time:.2f}秒")
    print(f"📊 特征工程结果: {df_with_features.shape[0]} 行 × {df_with_features.shape[1]} 列")
    
    # 查看缓存信息
    cache_info = get_cache_info(cache_path)
    print(f"📦 缓存信息:")
    print(f"   - 市场数据日期数: {cache_info['market_dates_count']}")
    print(f"   - 交易量数据日期数: {cache_info['volume_dates_count']}")
    print(f"   - 日期范围: {cache_info['date_range']}")
    print(f"   - 文件大小: {cache_info['file_size']}")
    
    # 场景2：重复运行（使用缓存）
    print("\n" + "="*60)
    print("⚡ 场景2：重复运行（使用缓存）")
    print("="*60)
    
    print("🔄 开始第二次特征工程（应该使用缓存）...")
    start_time = time.time()
    df_with_features_2 = add_market_features(df.copy(), cache_path=cache_path)
    second_run_time = time.time() - start_time
    
    print(f"⏱️ 第二次运行耗时: {second_run_time:.2f}秒")
    
    # 计算性能提升
    if second_run_time < first_run_time:
        improvement = (first_run_time - second_run_time) / first_run_time * 100
        print(f"🚀 缓存带来的性能提升: {improvement:.1f}%")
        print(f"⚡ 速度提升: {first_run_time / second_run_time:.1f}倍")
    
    # 验证结果一致性
    if df_with_features.shape == df_with_features_2.shape:
        print("✅ 两次运行结果完全一致")
    else:
        print("❌ 两次运行结果不一致")
    
    # 场景3：增量数据（部分使用缓存）
    print("\n" + "="*60)
    print("📈 场景3：增量数据（部分使用缓存）")
    print("="*60)
    
    # 创建包含新日期的数据
    new_dates = pd.date_range('2024-06-25', '2024-07-05', freq='D')  # 包含一些重叠和新日期
    
    new_data_rows = []
    for date in new_dates:
        for fund_code in fund_codes[:3]:  # 只取前3个基金
            apply_amt = abs(hash(f"{fund_code}_{date}_apply_new") % 50000) + 10000
            redeem_amt = abs(hash(f"{fund_code}_{date}_redeem_new") % 30000) + 5000
            uv1 = abs(hash(f"{fund_code}_{date}_uv1_new") % 2000) + 500
            uv2 = abs(hash(f"{fund_code}_{date}_uv2_new") % 1500) + 300
            uv3 = abs(hash(f"{fund_code}_{date}_uv3_new") % 1000) + 200
            
            new_data_rows.append({
                'fund_code': fund_code,
                'transaction_date': date,
                'apply_amt': apply_amt,
                'redeem_amt': redeem_amt,
                'uv_key_page_1': uv1,
                'uv_key_page_2': uv2,
                'uv_key_page_3': uv3
            })
    
    new_df = pd.DataFrame(new_data_rows)
    print(f"📊 新增数据: {new_df.shape[0]} 行，{len(fund_codes[:3])} 个基金，{len(new_dates)} 天")
    print(f"📅 新日期范围: {new_df['transaction_date'].min().strftime('%Y-%m-%d')} 到 {new_df['transaction_date'].max().strftime('%Y-%m-%d')}")
    
    # 查看缓存状态
    cache_info_before = get_cache_info(cache_path)
    print(f"📦 处理前缓存包含: {cache_info_before['market_dates_count']} 个日期")
    
    print("🔄 开始增量特征工程...")
    start_time = time.time()
    new_df_with_features = add_market_features(new_df.copy(), cache_path=cache_path)
    incremental_run_time = time.time() - start_time
    
    print(f"⏱️ 增量运行耗时: {incremental_run_time:.2f}秒")
    
    # 查看更新后的缓存状态
    cache_info_after = get_cache_info(cache_path)
    print(f"📦 处理后缓存包含: {cache_info_after['market_dates_count']} 个日期")
    print(f"📈 新增缓存日期: {cache_info_after['market_dates_count'] - cache_info_before['market_dates_count']} 个")
    
    # 场景4：强制刷新缓存
    print("\n" + "="*60)
    print("🔄 场景4：强制刷新缓存")
    print("="*60)
    
    # 使用小样本数据测试强制刷新
    sample_df = df.head(10).copy()  # 只取前10行
    
    print("🔄 开始强制刷新缓存...")
    start_time = time.time()
    sample_df_refreshed = add_market_features(
        sample_df.copy(), 
        cache_path=cache_path, 
        force_refresh=True
    )
    refresh_time = time.time() - start_time
    
    print(f"⏱️ 强制刷新耗时: {refresh_time:.2f}秒")
    print("✅ 强制刷新完成")
    
    # 总结
    print("\n" + "="*80)
    print("📊 性能对比总结")
    print("="*80)
    
    print(f"🕐 首次运行（创建缓存）: {first_run_time:.2f}秒")
    print(f"⚡ 缓存复用运行: {second_run_time:.2f}秒")
    print(f"📈 增量更新运行: {incremental_run_time:.2f}秒")
    print(f"🔄 强制刷新运行: {refresh_time:.2f}秒")
    
    if second_run_time < first_run_time:
        print(f"\n🚀 缓存机制带来的性能提升:")
        print(f"   - 速度提升: {first_run_time / second_run_time:.1f}倍")
        print(f"   - 时间节省: {first_run_time - second_run_time:.2f}秒")
        print(f"   - 效率提升: {(first_run_time - second_run_time) / first_run_time * 100:.1f}%")
    
    # 最终缓存信息
    final_cache_info = get_cache_info(cache_path)
    print(f"\n📦 最终缓存状态:")
    print(f"   - 缓存文件: {cache_path}")
    print(f"   - 市场数据日期数: {final_cache_info['market_dates_count']}")
    print(f"   - 日期范围: {final_cache_info['date_range']}")
    print(f"   - 文件大小: {final_cache_info['file_size']}")
    print(f"   - 创建时间: {final_cache_info['timestamp']}")
    
    # 清理演示缓存
    print(f"\n🗑️ 清理演示缓存文件...")
    clear_market_features_cache(cache_path)
    print("✅ 清理完成")

def show_cache_management_tips():
    """展示缓存管理的最佳实践"""
    print("\n" + "="*80)
    print("💡 市场特征缓存使用建议")
    print("="*80)
    
    tips = [
        "1. 📁 缓存文件默认保存为 'market_features_cache.pkl'，可以自定义路径",
        "2. ⚡ 相同日期的市场数据会自动复用，大幅提升处理速度",
        "3. 📈 新增日期会自动增量更新到缓存中，无需重新获取所有数据",
        "4. 🔄 使用 force_refresh=True 可以强制刷新缓存（忽略现有数据）",
        "5. 📊 使用 get_cache_info() 可以查看缓存的详细信息",
        "6. 🗑️ 使用 clear_market_features_cache() 可以清理缓存文件",
        "7. 💾 缓存文件可以在团队间共享，避免重复的API请求",
        "8. ⏰ 建议定期清理过期的缓存数据，保持文件大小合理",
        "9. 🔒 缓存文件包含市场指数和交易量数据，不包含基金净值（因基金而异）",
        "10. 🚀 在生产环境中，缓存可以显著减少API调用次数和响应时间"
    ]
    
    for tip in tips:
        print(f"   {tip}")
    
    print(f"\n📝 代码示例:")
    print(f"   ```python")
    print(f"   # 基本使用")
    print(f"   df = add_market_features(df)")
    print(f"   ")
    print(f"   # 指定缓存路径")
    print(f"   df = add_market_features(df, cache_path='my_cache.pkl')")
    print(f"   ")
    print(f"   # 强制刷新缓存")
    print(f"   df = add_market_features(df, force_refresh=True)")
    print(f"   ")
    print(f"   # 查看缓存信息")
    print(f"   info = get_cache_info('market_features_cache.pkl')")
    print(f"   ")
    print(f"   # 清理缓存")
    print(f"   clear_market_features_cache('market_features_cache.pkl')")
    print(f"   ```")

def main():
    """主函数"""
    print(f"⏰ 开始时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    
    try:
        # 演示缓存使用
        demonstrate_cache_usage()
        
        # 显示使用建议
        show_cache_management_tips()
        
        print(f"\n🎉 演示完成！市场特征缓存机制已经准备就绪。")
        
    except KeyboardInterrupt:
        print(f"\n⚠️ 演示被用户中断")
    except Exception as e:
        print(f"\n❌ 演示过程中出现异常: {e}")
        import traceback
        traceback.print_exc()
    
    print(f"⏰ 结束时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")

if __name__ == "__main__":
    main() 